﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Diagnostics.Contracts;
using System.Collections.ObjectModel;
using YasharEl.Infrastructure.ObjectFactory;

namespace YasharEl.Infrastructure.ApplicationModel.Bootstrap.Execution
{
    /// <summary>
    /// Execution context implementation which is also responsible for creating executable contexts.
    /// The IDescribable is released right after creation.
    /// </summary>
    public class ExecutionContext : IExecutionContext
    {
        private readonly ICollection<IExecutableContext> executables;

        /// <summary>
        /// Initializes a new instance of the <see cref="ExecutionContext"/> class.
        /// </summary>
        /// <param name="describable">The describable.</param>
        public ExecutionContext(IDescribable describable,BaseDependencyContainer container)
        {
            Contract.Requires<ArgumentNullException>(describable != null, "describable could not be null.");
            Contract.Requires<ArgumentNullException>(container != null, "container could not be null.");

            this.executables = new Collection<IExecutableContext>();

            this.Name = describable.Name;
            this.Description = describable.Describe();
            this.Container = container;
        }

        public string Name { get; private set; }

        public string Description { get; private set; }

        public BaseDependencyContainer Container
        {
            get;
            private set;
        }

        public IEnumerable<IExecutableContext> Executables
        {
            get
            {
                return this.executables;
            }
        }

        public IExecutableContext CreateExecutableContext(IDescribable describable)
        {
            var executableInfo = this.CreateExecutableContextCore(describable);

            this.executables.Add(executableInfo);

            return executableInfo;
        }

        /// <summary>
        /// Creates the executable context implementation.
        /// </summary>
        /// <param name="describable">The describable which is passed to the executable context.</param>
        /// <returns>A new instance of the executable context implementation.</returns>
        protected virtual IExecutableContext CreateExecutableContextCore(IDescribable describable)
        {
            return new ExecutableContext(describable,Container);
        }
    }
}
